<?php
/**
 * appRain v 0.1.x
 *
 * LICENSE
 *
 * This source file is subject to the MIT license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.opensource.org/licenses/mit-license.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@apprain.com so we can send you a copy immediately.
 *
 * @copyright  Copyright (c) 2010 appRain, Inc. (http://www.apprain.com)
 * @license    http://www.opensource.org/licenses/mit-license.php MIT license
 *
 * HELP
 * 
 * Official Website 
 * http://www.apprain.com/
 *
 * Download Link
 * http://www.apprain.com/download
 *
 * Documents Link
 * http ://www.apprain.com/documents
 */

abstract class appRain_Base_Modules_search extends appRain_Base_Objects
{
	public $searchPool = Array();
	const LINK_RELATIVE = 'Relative';
	const LINK_ABSOLUTE = 'Absolute';
	const CACHE_PRE_FIX = '__search__';
	const PARMA_DESC_LEANGTH = 200;

	public function search($srt = "")
	{
		if( $srt == "" ) return "";
		
		$this->setSearchString($srt);
		
		if(!$this->hasCache())
		{
			$this->searchPool = Array();
			
			App::__obj("Development_Callbacks")->_before_search_init($this);
			
			foreach(App::__def()->getCategorySetList() as $name )
			{
				$srcStr = $this->CategorySetSearchData($name);
				if(!empty($srcStr))
				{
					$this->searchPool = array_merge($this->searchPool,$srcStr);
				}
			}
			
			foreach(App::__def()->getInformationSetList() as $type )
			{
				$srcStr = $this->getSearchableFields($type);
				if(!empty($srcStr))
				{
					$this->searchPool = array_merge($this->searchPool,$this->processInformationSet($type,$srcStr));
				}
			}
			
			App::__obj("Development_Callbacks")->_after_search_init($this);
			
			$this->createCache();
		}
		else
		{
			$this->searchPool = $this->readCache();
		}
		
		return App::Helper('Utility')->array_paginator($this->searchPool,Array('limit'=>$this->getLimit(),'h_link'=>$this->getHLink(),'page'=>$this->getPage(),'smart'=>$this->getSmartPaging()));
	}
	
	private function readCache()
	{
		if(app::__def()->sysConfig('SEARCH_CACHE') == 'File')  return App::Module('Cache')->Read($this->cacheKey());	
		else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session') return App::Module('Session')->Read($this->cacheKey());	
	}
	
	private function createCache()
	{
		if(!empty($this->searchPool))
		{
			if(app::__def()->sysConfig('SEARCH_CACHE') == 'File')  App::Module('Cache')->Write($this->cacheKey(),$this->searchPool);
			else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session') App::Module('Session')->Write($this->cacheKey(),$this->searchPool);
		}

		return $this;
	}
	
	private function hasCache()
	{
		if(app::__def()->sysConfig('SEARCH_CACHE') == 'NoCache') return false;
		else if(app::__def()->sysConfig('SEARCH_CACHE') == 'File') return App::Module('Cache')->exists($this->cacheKey());
		else if(app::__def()->sysConfig('SEARCH_CACHE') == 'Session'){return App::Module('Session')->exists($this->cacheKey());}
	}
	
	private function cacheKey()
	{
		return self::CACHE_PRE_FIX . App::Helper('Utility')->text2Normalize($this->getSearchString());
	}
	
	private function categorySetSearchData($name)
	{
		$definition = App::__def()->getCategorySetDefinition($name);
		$definition['search']['status'] = isset($definition['search']['status']) ? $definition['search']['status'] : "No";
		$srcstr = $this->getSearchString();
		$data = Array();
		if( $definition['search']['status'] == 'Yes')
		{
			$tmp = App::CategorySet($name)->findAll("title LIKE '%{$srcstr}%' OR description LIKE '%{$srcstr}%'");
			foreach($tmp['data'] as $key => $val)
			{
				$uri = str_replace('[id]',$val['id'],$definition['search']['parma-link']['uri']);
				$uri = str_replace('[title]',App::Helper('Utility')->text2Normalize($val[$definition['search']['field-selected']]),$uri);

				if(ucfirst($definition['search']['parma-link']['type']) ==  self::LINK_ABSOLUTE)
				{
					$val['_parmalink'] = App::Helper('Html')->linkTag($uri,$val[$definition['search']['field-selected']]);	
				}
				else
				{
					$val['_parmalink'] = App::Helper('Html')->linkTag(App::Helper('Config')->baseurl("/{$uri}"),$val[$definition['search']['field-selected']]);
				}
				
				$val['_parmadesc'] = substr($val['description'],0,self::PARMA_DESC_LEANGTH);
				$data[] = $val;
			}
		}
		return $data;
	}
	
	private function processInformationSet($type=null, $srcStr=null)
	{
		$definition = App::__def()->getInformationSetDefinition($type);
		$result = App::InformationSet($type)->FindAll($srcStr);

		$data = Array();
		foreach($result['data'] as $val)
		{
			$uri = $definition['base']['search']['parma-link']['uri'];
			
			foreach(explode("/",$uri) as $needle)
			{
				if( substr($needle,0,1) == "[" && (substr($needle,(strlen($needle)-1),(strlen($needle)))) == "]")
				{
					$field = substr($needle,1,strlen($needle)-2);
					
					$uri = str_replace($needle,$val[$field],$uri);
				}
			}
						
			if(ucfirst($definition['base']['search']['parma-link']['type']) ==  self::LINK_ABSOLUTE)
			{
				$val['_parmalink'] = App::Helper('Html')->linkTag($uri,$val[$definition['base']['search']['field-selected']]);
			}
			else
			{
				$val['_parmalink'] = App::Helper('Html')->linkTag(App::Helper('Config')->baseurl("/{$uri}"),$val[$definition['base']['search']['field-selected']]);
			}
			
			$val['_parmadesc'] = isset($val[$definition['base']['search']['field-description']]) ? substr($val[$definition['base']['search']['field-description']],0,self::PARMA_DESC_LEANGTH) : "";
			
			$data[] = $val;
		}
		return $data;
	}
	
	private function getSearchableFields($type)
	{
		$definition = App::__def()->getInformationSetDefinition($type);
		
		$srcStr = Array();
		$definition['base']['search']['status'] = isset($definition['base']['search']['status']) ? $definition['base']['search']['status'] : "No";
		if(strtolower($definition['base']['search']['status']) == 'yes')
		{
			$i = 0;
			foreach($definition['fields'] as $name => $field)
			{
				if(strtolower($field['searchable']) == 'yes')
				{
					if(!empty($srcStr))
					{
						if($i%2 == 0)
						{
							$srcStr[] = 'OR';
						}
					}
					
					$srcStr[] = Array($name=>'%' . $this->getSearchString() . '%',"cnd"=>"LIKE");
				}
			}
		}
		return $srcStr;
	}
}